package hr.ctg.domain.model;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.validator.Email;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotNull;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.util.Base64;

@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "korisnik", uniqueConstraints = {})
@NamedQueries( {
		@NamedQuery(name = "Korisnik.findByUsernamePasswordRola", query = "select k from Korisnik k join k.rolas r where k.username=? and k.password=? and r.naziv = ?"),
		@NamedQuery(name = "Korisnik.findByUsernamePasswordAktivan", query = "select k from Korisnik k where k.username=? and k.password = ? and k.aktivan = ?"),
		@NamedQuery(name = "Korisnik.findByUsernameAktivan", query = "select k from Korisnik k where k.username=? and k.aktivan = ?"),
		@NamedQuery(name = "Korisnik.findByUsername", query = "select k from Korisnik k where k.username=?"),
		@NamedQuery(name = "Korisnik.findByEmailPasswordRola", query = "select k from Korisnik k join k.rolas r where k.email=? and k.password=? and r.naziv = ?"),
		@NamedQuery(name = "Korisnik.findByEmail", query = "select k from Korisnik k where k.email=?"),
		@NamedQuery(name = "Korisnik.getKorisnikCount", query = "select COUNT(k) from Korisnik k") })
@Name(value = "korisnik")
public class Korisnik implements java.io.Serializable {

	// Fields
	private static final long serialVersionUID = 1L;

	private Integer idKorisnika;
	private String ime;
	private String prezime;
	private Drzava drzava;
	private String mjesto;
	private Integer postanskiBroj;
	private String email;
	private String password;
	private boolean aktivan;
	private String username;
	private String telefon;
	private String mobTelefon;
	private String www;
	private Date zadnjeAzuriranje;
	private String kontaktIme;
	private byte[] logo;
	private String adresa;
	private String maticniBroj;
	private String tipLoga;
	// private Jezik jezik;

	private Set<DnevnikAktivnosti> dnevnikAktivnostis = new HashSet<DnevnikAktivnosti>(
			0);
	private Set<Rola> rolas = new HashSet<Rola>(0);
	private Set<DojamPosjetiteljaPortala> dojamPosjetiteljaPortalas = new HashSet<DojamPosjetiteljaPortala>(
			0);
	private Set<Slika> slikas = new HashSet<Slika>(0);
	private Set<DojamPosjetitelja> dojamPosjetiteljas = new HashSet<DojamPosjetitelja>(
			0);
	private Set<Objava> objavas = new HashSet<Objava>(0);
	private Set<Objekt> favorits = new HashSet<Objekt>(0);
	private Set<Objekt> objekts = new HashSet<Objekt>(0);
	private Set<Objekt> oglases = new HashSet<Objekt>(0);
	private Set<Dogadjaj> dogadjajs = new HashSet<Dogadjaj>(0);

	// Constructors

	/** default constructor */
	public Korisnik() {
		this.drzava = new Drzava(365);
	}

	/** minimal constructor */
	public Korisnik(final Integer idKorisnika, final String ime,
			final String email) {
		this.idKorisnika = idKorisnika;
		this.ime = ime;
		this.email = email;
		this.drzava = new Drzava(365);
	}

	/** full constructor */
	public Korisnik(final Integer idKorisnika, final String ime,
			final String email,
			final Set<DnevnikAktivnosti> dnevnikAktivnostis,
			final Set<Rola> rolas,
			final Set<DojamPosjetiteljaPortala> dojamPosjetiteljaPortalas,
			final Set<Slika> slikas,
			final Set<DojamPosjetitelja> dojamPosjetiteljas) {
		this.idKorisnika = idKorisnika;
		this.ime = ime;
		this.email = email;
		this.dnevnikAktivnostis = dnevnikAktivnostis;
		this.rolas = rolas;
		this.dojamPosjetiteljaPortalas = dojamPosjetiteljaPortalas;
		this.slikas = slikas;
		this.dojamPosjetiteljas = dojamPosjetiteljas;
		this.drzava = new Drzava(365);
	}

	@SuppressWarnings("unused")
	@PreUpdate
	@PrePersist
	private void preAction() {
		setZadnjeAzuriranje(new Date());
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "korisnik")
	public Set<DnevnikAktivnosti> getDnevnikAktivnostis() {
		return dnevnikAktivnostis;
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "korisnik")
	public Set<DojamPosjetitelja> getDojamPosjetiteljas() {
		return dojamPosjetiteljas;
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "korisnik")
	public Set<DojamPosjetiteljaPortala> getDojamPosjetiteljaPortalas() {
		return dojamPosjetiteljaPortalas;
	}

	@Column(name = "email", unique = false, nullable = false, insertable = true, updatable = true, length = 50)
	@Email
	@NotNull
	public String getEmail() {
		return email;
	}

	// Property accessors
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id_korisnika", unique = true, nullable = false)
	public Integer getIdKorisnika() {
		return idKorisnika;
	}

	@NotNull
	@Length(max = 30)
	@Column(name = "ime", unique = false, nullable = false, insertable = true, updatable = true, length = 30)
	public String getIme() {
		return ime;
	}

	@Column(name = "password", unique = false, nullable = false, insertable = true, updatable = true, length = 20)
	@Length(min = 5, max = 20)
	public String getPassword() {
		return password;
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "korisniks")
	public Set<Rola> getRolas() {
		return rolas;
	}

	public boolean containRola(int idRole) {
		if (rolas != null) {
			for (Rola rola : rolas) {
				if (rola.getIdRole() == idRole) {
					return true;
				}
			}
		}
		return false;
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "korisnik")
	public Set<Slika> getSlikas() {
		return slikas;
	}

	@Column(name = "aktivan", unique = false, nullable = false, insertable = true, updatable = true)
	public boolean isAktivan() {
		return aktivan;
	}

	public void setAktivan(final boolean aktivan) {
		this.aktivan = aktivan;
	}

	public void setDnevnikAktivnostis(
			final Set<DnevnikAktivnosti> dnevnikAktivnostis) {
		this.dnevnikAktivnostis = dnevnikAktivnostis;
	}

	public void setDojamPosjetiteljas(
			final Set<DojamPosjetitelja> dojamPosjetiteljas) {
		this.dojamPosjetiteljas = dojamPosjetiteljas;
	}

	public void setDojamPosjetiteljaPortalas(
			final Set<DojamPosjetiteljaPortala> dojamPosjetiteljaPortalas) {
		this.dojamPosjetiteljaPortalas = dojamPosjetiteljaPortalas;
	}

	public void setEmail(final String email) {
		this.email = email;
	}

	public void setIdKorisnika(final Integer idKorisnika) {
		this.idKorisnika = idKorisnika;
	}

	public void setIme(final String ime) {
		this.ime = ime;
	}

	public void setPassword(final String password) {
		this.password = password;
	}

	public void setRolas(final Set<Rola> rolas) {
		this.rolas = rolas;
	}

	public void setSlikas(final Set<Slika> slikas) {
		this.slikas = slikas;
	}

	@Column(name = "username")
	public String getUsername() {
		return username;
	}

	public void setUsername(final String username) {
		this.username = username;
	}

	@Transient
	public String getKey() {
		return Base64.encodeBytes(username.getBytes());
	}

	@Column(name = "telefon")
	public String getTelefon() {
		return telefon;
	}

	public void setTelefon(final String telefon) {
		this.telefon = telefon;
	}

	@Column(name = "www")
	public String getWww() {
		return www;
	}

	public void setWww(final String www) {
		this.www = www;
	}

	@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "id_drzave", nullable = false)
	public Drzava getDrzava() {
		return drzava;
	}

	public void setDrzava(final Drzava drzava) {
		this.drzava = drzava;
	}

	@NotNull
	@Column(name = "mjesto", nullable = false)
	public String getMjesto() {
		return mjesto;
	}

	public void setMjesto(final String mjesto) {
		this.mjesto = mjesto;
	}

	@NotNull
	@Column(name = "postanski_broj", nullable = false)
	public Integer getPostanskiBroj() {
		return postanskiBroj;
	}

	public void setPostanskiBroj(final Integer postanskiBroj) {
		this.postanskiBroj = postanskiBroj;
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "korisnik")
	public Set<Objava> getObjavas() {
		return objavas;
	}

	public void setObjavas(final Set<Objava> objavas) {
		this.objavas = objavas;
	}

	public boolean hasRola(final String rola) {
		for (final Rola r : getRolas()) {
			if (r.getNaziv().equals(rola)) {
				return true;
			}
		}
		return false;
	}

	@Column(name = "zadnje_azuriranje")
	public Date getZadnjeAzuriranje() {
		return zadnjeAzuriranje;
	}

	public void setZadnjeAzuriranje(final Date zadnjeAzuriranje) {
		this.zadnjeAzuriranje = zadnjeAzuriranje;
	}

	@Column(name = "kontakt_ime")
	public String getKontaktIme() {
		return kontaktIme;
	}

	public void setKontaktIme(final String kontaktIme) {
		this.kontaktIme = kontaktIme;
	}

	@Column(name = "logo")
	public byte[] getLogo() {
		return logo;
	}

	public void setLogo(final byte[] logo) {
		this.logo = logo;
	}

	@Column(name = "mob_telefon")
	public String getMobTelefon() {
		return mobTelefon;
	}

	public void setMobTelefon(final String mobTelefon) {
		this.mobTelefon = mobTelefon;
	}

	public String getAdresa() {
		return adresa;
	}

	@Column(name = "adresa")
	public void setAdresa(final String adresa) {
		this.adresa = adresa;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime
				* result
				+ ((getIdKorisnika() == null) ? 0 : getIdKorisnika().hashCode());
		return result;
	}

	@Override
	public boolean equals(final Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		final Korisnik other = (Korisnik) obj;
		if (getIdKorisnika() == null) {
			if (other.getIdKorisnika() != null)
				return false;
		} else if (!getIdKorisnika().equals(other.getIdKorisnika()))
			return false;
		return true;
	}

	@Column(name = "maticni_broj")
	public String getMaticniBroj() {
		return maticniBroj;
	}

	public void setMaticniBroj(final String maticniBroj) {
		this.maticniBroj = maticniBroj;
	}

	@Column(name = "tip_loga")
	public String getTipLoga() {
		return tipLoga;
	}

	public void setTipLoga(final String tipLoga) {
		this.tipLoga = tipLoga;
	}

	@Length(max = 20)
	@Column(name = "prezime", unique = false, insertable = true, updatable = true, length = 0)
	public String getPrezime() {
		return prezime;
	}

	public void setPrezime(final String prezime) {
		this.prezime = prezime;
	}

	public void setDogadjajs(final Set<Dogadjaj> dogadjajs) {
		this.dogadjajs = dogadjajs;
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "korisnik")
	public Set<Dogadjaj> getDogadjajs() {
		return dogadjajs;
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "motriteljs")
	public Set<Objekt> getFavorits() {
		return favorits;
	}

	public void setFavorits(final Set<Objekt> favorits) {
		this.favorits = favorits;
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "autor")
	public Set<Objekt> getObjekts() {
		return objekts;
	}

	public void setObjekts(final Set<Objekt> objekts) {
		this.objekts = objekts;
	}

	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "oglasivac")
	public Set<Objekt> getOglases() {
		return oglases;
	}

	public void setOglases(final Set<Objekt> oglases) {
		this.oglases = oglases;
	}
}